//Copyright (C) 2007 James Ashley (www.imaginativeuniversal.com) under the terms of the LGPL.
using System;
using System.Collections.Generic;
using System.Speech.Recognition;
using System.Drawing;
using System.Text;

namespace SophiaBot
{
    public class SpeechCommandBot: BotServerBase
    {

        #region local fields

        protected readonly string CHANGEFONTCOLORTO = "CHANGE FONT COLOR TO";
        protected readonly string CHANGECOLORTO = "CHANGE COLOR TO";
        protected readonly string CHANGEFOREGROUNDCOLORTO = "CHANGE FOREGROUND COLOR TO";
        protected readonly string CHANGEBACKGROUNDCOLORTO = "CHANGE BACKGROUND COLOR TO";
        protected readonly string CHANGEFONTTO = "CHANGE FONT TO";
        protected readonly string LISTCOLORS = "LIST COLORS";
        protected readonly string LISTFONTS = "LIST FONTS";
        protected readonly string LISTGAMEKEYWORDS = "LIST GAME KEYWORDS";
        
        private GameEngineBot _gameEngineBot = null;

        #endregion

        #region constructor

        public SpeechCommandBot()
        {
            _name = "Speech Command";
        }

        #endregion

        #region IBotServer Members

        /// <summary>
        /// Reads the specified input text.
        /// </summary>
        /// <param name="inputText">The input text.</param>
        public override void Read(string inputText)
        {
            if(null != _nextBot)
                _nextBot.Read(inputText);
        }

        /// <summary>
        /// Gets the grammar.
        /// </summary>
        /// <returns></returns>
        public override Grammar[] GetGrammars()
        {
            Grammar g = GetSpeechCommandGrammar();
            g.Priority = this._priority;
            g.Name = this._name;
            g.SpeechRecognized += new EventHandler<SpeechRecognizedEventArgs>(SpeechCommands_SpeechRecognized);
            return new Grammar[1]{g};
        }


        /// <summary>
        /// Starts the specified val.
        /// </summary>
        /// <param name="val">The val.</param>
        public override void Start(string val)
        {
            Start();
        }

        #endregion

        #region helper methods and properties

        /// <summary>
        /// Handles the speech commands.
        /// </summary>
        /// <param name="recognizedText">The recognized text.</param>
        protected virtual void HandleSpeechCommands(string recognizedText)
        {
            if (_isRunning)
            {
                string color = string.Empty;
                if (recognizedText.IndexOf(CHANGEFONTCOLORTO) > -1)
                {
                    color = recognizedText.Substring(recognizedText.IndexOf(CHANGEFONTCOLORTO, StringComparison.CurrentCultureIgnoreCase) + CHANGEFONTCOLORTO.Length + 1);
                    Color fontColor = Color.FromName(color);
                    if (null != OnChangeFontColor)
                    {
                        OnChangeFontColor(fontColor);
                    }
                }
                else if (recognizedText.IndexOf(CHANGECOLORTO) > -1)
                {
                    color = recognizedText.Substring(recognizedText.IndexOf(CHANGECOLORTO, StringComparison.CurrentCultureIgnoreCase) + CHANGECOLORTO.Length + 1);
                    Color fontColor = Color.FromName(color);
                    if (null != OnChangeFontColor)
                    {
                        OnChangeFontColor(fontColor);
                    }
                }
                else if (recognizedText.IndexOf(CHANGEFOREGROUNDCOLORTO) > -1)
                {
                    color = recognizedText.Substring(recognizedText.IndexOf(CHANGEFOREGROUNDCOLORTO, StringComparison.CurrentCultureIgnoreCase) + CHANGEFOREGROUNDCOLORTO.Length + 1);
                    Color fontColor = Color.FromName(color);
                    if (null != OnChangeFontColor)
                    {
                        OnChangeFontColor(fontColor);
                    }
                }
                else if (recognizedText.IndexOf(CHANGEBACKGROUNDCOLORTO) > -1)
                {
                    color = recognizedText.Substring(recognizedText.IndexOf(CHANGEBACKGROUNDCOLORTO, StringComparison.CurrentCultureIgnoreCase) + CHANGEBACKGROUNDCOLORTO.Length + 1);
                    Color backgroundColor = Color.FromName(color);
                    if (null != OnChangeBackgroundColor)
                    {
                        OnChangeBackgroundColor(backgroundColor);
                    }
                }
                else if (recognizedText.IndexOf(CHANGEFONTTO) > -1)
                {
                    string fontName = recognizedText.Substring(recognizedText.IndexOf(CHANGEFONTTO, StringComparison.CurrentCultureIgnoreCase) + CHANGEFONTTO.Length + 1);
                    if (null != OnChangeFont)
                    {
                        OnChangeFont(fontName);
                    }
                }
                else if (recognizedText.IndexOf(LISTCOLORS, StringComparison.CurrentCultureIgnoreCase)>-1)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (string knownColor in Enum.GetNames(typeof(KnownColor)))
                    {
                        sb.Append(", " + knownColor);
                    }
                    RaiseBotInfoResponseEvent(this, sb.ToString().Substring(2));
                }
                else if (recognizedText.IndexOf(LISTFONTS, StringComparison.CurrentCultureIgnoreCase) > -1)
                {
                    StringBuilder sb = new StringBuilder();
                    foreach (FontFamily font in (new System.Drawing.Text.InstalledFontCollection()).Families)
                    {
                        sb.Append(", " + font.Name);
                    }
                    RaiseBotInfoResponseEvent(this, sb.ToString().Substring(2));
                }
                else if (recognizedText.IndexOf(LISTGAMEKEYWORDS, StringComparison.CurrentCultureIgnoreCase) > -1)
                {
                    if (_gameEngineBot != null)
                    {
                        RaiseBotInfoResponseEvent(this, _gameEngineBot.ListGameKeywords());
                    }
                    else
                        RaiseBotResponseEvent(this, "No game has been loaded.");
                }
                else
                {
                    if (null != _nextBot)
                        _nextBot.Read(recognizedText);
                }
            }
            else
            {
                if (null != _nextBot)
                    _nextBot.Read(recognizedText);
            }
        }

        protected virtual Grammar GetSpeechCommandGrammar()
        {
            GrammarBuilder gb = new GrammarBuilder();
            Choices choices = new Choices();

            GrammarBuilder changeFontColorCommand = new GrammarBuilder();
            GrammarBuilder changeColorCommand = new GrammarBuilder();
            GrammarBuilder changeBackgroundColorCommand = new GrammarBuilder();
            GrammarBuilder changeForegroundColorCommand = new GrammarBuilder();
            GrammarBuilder changeFontCommand = new GrammarBuilder();
            Choices colorChoices = new Choices();
            foreach (string colorName in System.Enum.GetNames(typeof(KnownColor)))
            {
                colorChoices.Add(colorName.ToUpper());
            }
            Choices fontChoices = new Choices();
            foreach (FontFamily font in (new System.Drawing.Text.InstalledFontCollection()).Families)
            {
                fontChoices.Add(font.Name.ToUpper());
            }
            changeFontColorCommand.Append(CHANGEFONTCOLORTO);
            changeFontColorCommand.Append(colorChoices);
            choices.Add(changeFontColorCommand);
            changeForegroundColorCommand.Append(CHANGEFOREGROUNDCOLORTO);
            changeForegroundColorCommand.Append(colorChoices);
            choices.Add(changeForegroundColorCommand);
            changeBackgroundColorCommand.Append(CHANGEBACKGROUNDCOLORTO);
            changeBackgroundColorCommand.Append(colorChoices);
            choices.Add(changeBackgroundColorCommand);
            changeColorCommand.Append(CHANGECOLORTO);
            changeColorCommand.Append(colorChoices);
            choices.Add(changeColorCommand);
            changeFontCommand.Append(CHANGEFONTTO);
            changeFontCommand.Append(fontChoices);
            choices.Add(changeFontCommand);
            choices.Add(LISTCOLORS);
            choices.Add(LISTGAMEKEYWORDS);
            choices.Add(LISTFONTS);
            gb.Append(choices);
            Grammar g = new Grammar(gb);
            return g;
        }

        #endregion

        #region public methods and properties

        public event GenericEventHandler<Color> OnChangeFontColor;
        public event GenericEventHandler<Color> OnChangeBackgroundColor;
        public event GenericEventHandler<string> OnChangeFont;

        /// <summary>
        /// Handles the SpeechRecognized event of the commands grammar.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Speech.Recognition.SpeechRecognizedEventArgs"/> instance containing the event data.</param>
        public void SpeechCommands_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
        {
            string resultText = e.Result.Text;
            RaiseTextRecognizedEvent(resultText);
            DebugWriteToConsole(resultText + " Recognized in Commands bot Grammar");
            HandleSpeechCommands(resultText);
        }

        /// <summary>
        /// Gets or sets the game engine bot.
        /// </summary>
        /// <value>The game engine bot.</value>
        public GameEngineBot GameEngineBot
        {
            get { return _gameEngineBot; }
            set { _gameEngineBot = value; }
        }

        #endregion
    }
}
